home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / workbench / directoryopus4 / dopus4_src / program / iffload.c < prev    next >
C/C++ Source or Header  |  2000-03-11  |  65KB  |  1,965 lines

  1. /*
  2.  
  3. Directory Opus 4
  4. Original GPL release version 4.12
  5. Copyright 1993-2000 Jonathan Potter
  6.  
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. All users of Directory Opus 4 (including versions distributed
  22. under the GPL) are entitled to upgrade to the latest version of
  23. Directory Opus version 5 at a reduced price. Please see
  24. http://www.gpsoft.com.au for more information.
  25.  
  26. The release of Directory Opus 4 under the GPL in NO WAY affects
  27. the existing commercial status of Directory Opus 5.
  28.  
  29. */
  30.  
  31. #include "dopus.h"
  32. #include <proto/powerpacker.h>
  33. #include "pchg.h"
  34.  
  35. enum {
  36.     PRINT_ASPECT,
  37.     PRINT_IMAGE,
  38.     PRINT_SHADE,
  39.     PRINT_PLACE,
  40.     PRINT_FORMFD,
  41.     PRINT_TITLE,
  42.     PRINT_OKAY,
  43.     PRINT_CANCEL,
  44.     PRINT_ABORT};
  45.  
  46. static ULONG *colourtable_8=NULL,ctsize;
  47. static UWORD *copperlist,*colourtable_4=NULL,colourlist[4];
  48. static struct View *view;
  49. static struct ViewPort *ivp;
  50. static char *picbuffer,*picturename;
  51. static unsigned char *bodyptr;
  52. static CRange cyclerange[6];
  53. static ULONG buffersize,bufferpos;
  54. static int
  55.     numcolours,currange,copperheight,viewmode,
  56.     screenwidth,screenheight,
  57.     imagewidth,imageheight,
  58.     bitmapwidth,bitmapheight,
  59.     minwidth,minheight,maxwidth,maxheight,depth,coppersize,
  60.     viewflags;
  61. static char specialformat;
  62. static BitMapHeader bmhead;
  63. static struct BitMap *iffbm[2];
  64. static struct Window *iffwindow;
  65. static struct DOpusRemember *iffkey;
  66.  
  67. #ifdef DO_DBUF
  68. static struct DBufInfo *dbufinfo;
  69. static struct MsgPort *dbufport;
  70. #endif
  71.  
  72. char iffscreenname[34]="";
  73.  
  74. struct AnimFrame {
  75.     struct AnimFrame *next;
  76.     AnimHdr *animheader;
  77.     unsigned char *delta;
  78.     unsigned char *cmap;
  79.     int cmapsize;
  80. };
  81.  
  82. static struct TagItem
  83.     loresscreentags[3]={
  84.         {SA_DisplayID,LORES_KEY},
  85.         {SA_Pens,(ULONG)scr_drawinfo},
  86.         {0,0}};
  87.  
  88. static struct ExtNewScreen
  89.     printscreen={
  90.         0,0,320,0,2,
  91.         0,1,0,
  92.         CUSTOMSCREEN|SCREENQUIET|SCREENBEHIND|NS_EXTENDED,
  93.         &screen_attr,NULL,NULL,NULL,loresscreentags};
  94.  
  95. static struct NewWindow
  96.     iffwin={
  97.         0,0,0,0,
  98.         255,255,
  99.         IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_INTUITICKS|IDCMP_INACTIVEWINDOW,
  100.         WFLG_RMBTRAP|WFLG_BORDERLESS|WFLG_SIMPLE_REFRESH|WFLG_NOCAREREFRESH,
  101.         NULL,NULL,NULL,NULL,NULL,
  102.         0,0,0,0,CUSTOMSCREEN},
  103.     printwin={
  104.         0,0,320,0,0,0,
  105.         IDCMP_GADGETUP|IDCMP_VANILLAKEY,
  106.         WFLG_RMBTRAP|WFLG_BORDERLESS,
  107.         NULL,NULL,NULL,NULL,NULL,
  108.         0,0,0,0,CUSTOMSCREEN};
  109.  
  110. static struct Image
  111.     printcheckimage={7,2,13,7,1,NULL,1,0,NULL},
  112.     printnullcheckimage={7,2,13,7,1,NULL,0,0,NULL},
  113.     animframeimage;
  114.  
  115. static struct Gadget
  116.     printgadgets[8]={
  117.         {&printgadgets[1],142,104,123,14,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  118.         NULL,NULL,NULL,GAD_CYCLE,NULL,PRINT_ASPECT,NULL},
  119.         {&printgadgets[2],142,120,123,14,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  120.         NULL,NULL,NULL,GAD_CYCLE,NULL,PRINT_IMAGE,NULL},
  121.         {&printgadgets[3],142,136,123,14,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  122.         NULL,NULL,NULL,GAD_CYCLE,NULL,PRINT_SHADE,NULL},
  123.         {&printgadgets[4],142,152,123,14,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  124.         NULL,NULL,NULL,GAD_CYCLE,NULL,PRINT_PLACE,NULL},
  125.         {&printgadgets[5],18,168,26,11,GFLG_GADGIMAGE|GFLG_GADGHIMAGE|GFLG_SELECTED,GACT_RELVERIFY|GACT_TOGGLESELECT,GTYP_BOOLGADGET,
  126.         (APTR)&printnullcheckimage,(APTR)&printcheckimage,NULL,GAD_CHECK,NULL,PRINT_FORMFD,NULL},
  127.         {&printgadgets[6],142,168,26,11,GFLG_GADGIMAGE|GFLG_GADGHIMAGE,GACT_RELVERIFY|GACT_TOGGLESELECT,GTYP_BOOLGADGET,
  128.         (APTR)&printnullcheckimage,(APTR)&printcheckimage,NULL,GAD_CHECK,NULL,PRINT_TITLE,NULL},
  129.         {&printgadgets[7],20,186,100,12,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  130.         NULL,NULL,NULL,0,NULL,PRINT_OKAY,NULL},
  131.         {NULL,196,186,100,12,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  132.         NULL,NULL,NULL,0,NULL,PRINT_CANCEL,NULL}},
  133.     abortprintgad={
  134.         NULL,60,0,200,80,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  135.         NULL,NULL,NULL,0,NULL,PRINT_ABORT,NULL};
  136.  
  137. char
  138.     *printgadtxt[9],
  139.     *printabortgadtxt[2]={NULL,NULL},
  140.     *print_aspect_txt[2],
  141.     *print_image_txt[2],
  142.     *print_shade_txt[3],
  143.     *print_placement_txt[2],
  144.  
  145.     **print_gads_txt[4]={
  146.         print_aspect_txt,
  147.         print_image_txt,
  148.         print_shade_txt,
  149.         print_placement_txt};
  150.  
  151. static char
  152.     print_gads_sel[4]={0,0,0,0},
  153.     print_gads_max[4]={1,1,2,1};
  154.  
  155. static struct AnimFrame
  156.     *first_anim_frame,*current_anim_frame,*last_anim_frame,
  157.     initial_anim_cmap;
  158. static int framecount,framenum,framedisp;
  159. static char doublebuffer;
  160. static int animspeed,framespersec,animrestart;
  161. static struct BitMap *animframe_bm[2],*initialframe_bm;
  162. static USHORT basepalette[4]={0xaaa,0x000,0xfff,0x679};
  163. static union printerIO *print_request; /* IO request for Print operation */
  164. static int palette32,got_dpan;
  165. static int animtype;
  166. static struct PCHGHeader *pchghead;
  167. static char *sham;
  168.  
  169. LoadPic(name)
  170. char *name;
  171. {
  172.     int
  173.         retcode,a,gotbody,brush,scroll,mp=1,isanim,extflag=0,
  174.         colourptr,coloursize,maxframes;
  175.     ULONG chunkid,chunksize,chunkbuf[3];
  176.     struct DimensionInfo *dimension;
  177.     DisplayInfoHandle *handle;
  178.     char dimbuf[256],*ptr;
  179.     DPAnimChunk dpan;
  180.     struct AnimFrame *cur_frame=NULL,*frame;
  181.  
  182.     picturename=name;
  183.     if (readfile(name,&picbuffer,(int *)&buffersize)) return(0);
  184.  
  185.     viewmode=-1; copperlist=NULL; iffwindow=NULL;
  186.     iffscreen=NULL; iffscreenname[0]=0;
  187.     copperheight=currange=gotbody=brush=0; scroll=1;
  188.     colourptr=-1; doublebuffer=0; animspeed=50000;
  189.     bodyptr=NULL; bufferpos=isanim=0; iffkey=NULL; first_anim_frame=NULL;
  190.     framecount=0; framespersec=20; maxframes=65535; specialformat=0;
  191.     initialframe_bm=NULL; palette32=0;
  192.     last_anim_frame=NULL; initial_anim_cmap.cmap=NULL;
  193.     got_dpan=0; animtype=0;
  194.     pchghead=NULL; sham=NULL;
  195.  
  196.     for (a=0;a<2;a++) {
  197.         iffbm[a]=NULL;
  198.         animframe_bm[a]=NULL;
  199.     }
  200.  
  201. #ifdef DO_DBUF
  202.     dbufinfo=NULL; dbufport=NULL;
  203. #endif
  204.  
  205.     if (!chunkread(chunkbuf,sizeof(ULONG)*3) ||
  206.         chunkbuf[0]!=ID_FORM ||
  207.         (chunkbuf[2]!=ID_ANIM && chunkbuf[2]!=ID_ILBM)) {
  208.         retcode=IFFERR_NOTILBM;
  209.         goto endiff;
  210.     }
  211.     if (chunkbuf[2]==ID_ANIM) isanim=1;
  212.  
  213.     while (bufferpos<=buffersize) {
  214.         if (!chunkread(&chunkid,sizeof(int)) ||
  215.             !chunkread(&chunksize,sizeof(int)) ||
  216.             ((bufferpos+chunksize)>buffersize)) break;
  217.         switch (chunkid) {
  218.             case ID_FORM:
  219.                 bufferpos+=4;
  220.                 continue;
  221.             case ID_DPAN:
  222.                 if (!isanim) break;
  223.                 if (!(chunkread(&dpan,sizeof(DPAnimChunk)))) {
  224.                     retcode=IFFERR_BADIFF;
  225.                     goto endiff;
  226.                 }
  227.                 chunksize=0;
  228.                 maxframes=dpan.nframes;
  229.                 if ((framespersec=dpan.framespersecond)>0)
  230.                     animspeed=1000000/dpan.framespersecond;
  231.                 got_dpan=1;
  232.                 break;
  233.             case ID_ANHD:
  234.                 if (isanim && framecount<maxframes &&
  235.                     (frame=LAllocRemember(&iffkey,sizeof(struct AnimFrame),MEMF_CLEAR))) {
  236.                     frame->animheader=(AnimHdr *)(picbuffer+bufferpos);
  237.                     if (frame->animheader->interleave!=1) doublebuffer=1;
  238.                     if (!animtype) animtype=frame->animheader->operation;
  239.  
  240.                     if (cur_frame) cur_frame->next=frame;
  241.                     else first_anim_frame=frame;
  242.                     cur_frame=frame;
  243.                 }
  244.                 break;
  245.             case ID_DLTA:
  246.                 if (isanim && framecount<maxframes && cur_frame) {
  247.                     cur_frame->delta=picbuffer+bufferpos;
  248.                     ++framecount;
  249.                 }
  250.                 break;
  251.             case ID_BMHD:
  252.                 if (!chunkread(&bmhead,sizeof(BitMapHeader))) {
  253.                     retcode=IFFERR_BADIFF;
  254.                     goto endiff;
  255.                 }
  256.                 chunksize=0;
  257.                 break;
  258.             case ID_CMAP:
  259.                 if (colourptr==-1) {
  260.                     colourptr=bufferpos; coloursize=chunksize;
  261.                     initial_anim_cmap.cmap=(unsigned char *)&picbuffer[bufferpos];
  262.                     initial_anim_cmap.cmapsize=chunksize;
  263.                 }
  264.                 else if (isanim && framecount<maxframes && cur_frame) {
  265.                     cur_frame->cmap=(unsigned char *)&picbuffer[bufferpos];
  266.                     cur_frame->cmapsize=chunksize;
  267.                 }
  268.                 break;
  269.             case ID_GRAB:
  270.                 brush=1;
  271.                 break;
  272.             case ID_CAMG:
  273.                 if (!chunkread(&viewmode,sizeof(int))) {
  274.                     retcode=IFFERR_BADIFF;
  275.                     goto endiff;
  276.                 }
  277.                 chunksize=0;
  278.                 break;
  279.             case ID_CTBL:
  280.                 if (copperlist=LAllocRemember(&iffkey,chunksize,MEMF_CLEAR)) {
  281.                     coppersize=chunksize;
  282.                     copperheight=chunksize/32;
  283.                     CopyMem((char *)&picbuffer[bufferpos],(char *)copperlist,chunksize);
  284.                     CopyMem((char *)&picbuffer[bufferpos],(char *)colourlist,8);
  285.                 }
  286.                 break;
  287.             case ID_DYCP:
  288.                 mp=0;
  289.                 break;
  290.             case ID_SHAM:
  291.                 if (!(pchghead=PCHG_SHAM2PCHG((UWORD *)&picbuffer[bufferpos],chunksize,(viewmode&LACE)?2:1))) {
  292.                     retcode=IFFERR_NOMEM;
  293.                     goto endiff;
  294.                 }
  295.                 sham=&picbuffer[bufferpos];
  296.                 specialformat=1;
  297.                 break;
  298.             case ID_PCHG:
  299.                 pchghead=(struct PCHGHeader *)&picbuffer[bufferpos];
  300.                 specialformat=1;
  301.                 break;
  302.             case ID_CRNG:
  303.                 if (currange<6) {
  304.                     CopyMem((char *)&picbuffer[bufferpos],(char *)&cyclerange[currange],sizeof(CRange));
  305.                     if (cyclerange[currange].rate<=CRNG_NORATE ||
  306.                         cyclerange[currange].low==cyclerange[currange].high)
  307.                         cyclerange[currange].active=0;
  308.                     if (cyclerange[currange].rate>CRNG_NORATE)
  309.                         cyclerange[currange].rate=16384/cyclerange[currange].rate;
  310.                     else cyclerange[currange].rate=0;
  311.                     ++currange;
  312.                 }
  313.                 break;
  314.             case ID_BODY:
  315.                 if (!gotbody) {
  316.                     gotbody=1;
  317.                     bodyptr=picbuffer+bufferpos;
  318.                 }
  319.                 break;
  320.         }
  321.         if (chunksize) {
  322.             bufferpos+=chunksize;
  323.             if (chunksize&1) ++bufferpos;
  324.         }
  325.     }
  326.  
  327.     if (!gotbody) {
  328.         retcode=IFFERR_BADIFF;
  329.         goto endiff;
  330.     }
  331.  
  332.     if (copperlist) specialformat=1;
  333.  
  334.     depth=bmhead.nPlanes;
  335.  
  336.     if (colourptr>-1) {
  337.         numcolours=coloursize/3;
  338.  
  339.         if (system_version2>=OSVER_39 && !specialformat)
  340.             colourtable_8=LAllocRemember(&iffkey,(coloursize+2)*4,MEMF_CLEAR);
  341.  
  342.         colourtable_4=LAllocRemember(&iffkey,numcolours*sizeof(UWORD),MEMF_CLEAR);
  343.     }
  344.  
  345.     if (!colourtable_8 && !colourtable_4) {
  346.         retcode=IFFERR_BADIFF;
  347.         goto endiff;
  348.     }
  349.  
  350.     if ((config->viewbits&VIEWBITS_8BITSPERGUN || bmhead.flags&BMHF_CMAPOK) &&
  351.         colourtable_8) palette32=1;
  352.  
  353.     build_palettes(&picbuffer[colourptr],coloursize,colourtable_4,colourtable_8);
  354.  
  355.     imagewidth=bmhead.w;
  356.     imageheight=bmhead.h;
  357.     screenwidth=bmhead.w;
  358.     screenheight=bmhead.h;
  359.  
  360.     minwidth=320;
  361.     minheight=200;
  362.  
  363.     maxwidth=368;
  364.     if (scrdata_is_pal) maxheight=281;
  365.     else maxheight=241;
  366.  
  367.     if (viewmode==-1 || brush) {
  368.         viewflags=viewmode; viewmode=0;
  369.         if (bmhead.pageWidth>maxwidth) viewmode|=HIRES;
  370.         if (bmhead.pageHeight>maxheight) viewmode|=LACE;
  371.         if (system_version2<OSVER_39) {
  372.             if (depth>6) {
  373.                 retcode=IFFERR_BADMODE;
  374.                 goto endiff;
  375.             }
  376.             if (depth==6) {
  377.                 if (viewflags==-1 || viewflags&HAM) viewmode|=HAM;
  378.                 else viewmode|=EXTRA_HALFBRITE;
  379.             }
  380.         }
  381.         viewflags=0;
  382.     }
  383.  
  384.     if (system_version2) {
  385.         if (viewmode&0xfffe000) {
  386.             if (!(ModeNotAvailable(viewmode))) extflag=1;
  387.             else if ((handle=FindDisplayInfo(viewmode)) &&
  388.                 (GetDisplayInfoData(handle,dimbuf,256,DTAG_NAME,0)))
  389.                 extflag=1;
  390.         }
  391.     }
  392.  
  393.     if (extflag) {
  394.         if (ModeNotAvailable(viewmode)) {
  395.             if (system_version2<OSVER_39) {
  396.                 retcode=IFFERR_BADMODE;
  397.                 goto endiff;
  398.             }
  399.             else viewmode=-1;
  400.         }
  401.  
  402.         if (system_version2>=OSVER_39 &&
  403.             (viewmode==-1 || config->viewbits&VIEWBITS_BESTMODEID)) {
  404.  
  405.             ULONG newmode;
  406.  
  407.             if (!(ModeNotAvailable((newmode=
  408.                 BestModeID(
  409.                     BIDTAG_NominalWidth,imagewidth,
  410.                     BIDTAG_NominalHeight,imageheight,
  411.                     BIDTAG_Depth,depth,
  412.                     BIDTAG_SourceID,viewmode,
  413.                     BIDTAG_MonitorID,(GetVPModeID(&Window->WScreen->ViewPort)&MONITOR_ID_MASK),
  414.                     TAG_END))))) viewmode=newmode;
  415.         }
  416.  
  417.         if (handle=FindDisplayInfo(viewmode)) {
  418.             if (!(a=GetDisplayInfoData(handle,dimbuf,256,DTAG_NAME,0))) {
  419.                 DisplayInfoHandle *temphandle;
  420.                 ULONG tempviewmode;
  421.  
  422.                 tempviewmode=viewmode;
  423.                 tempviewmode&=~(HAM_KEY|EXTRAHALFBRITE_KEY);
  424.  
  425.                 if ((temphandle=FindDisplayInfo(tempviewmode)))
  426.                     a=GetDisplayInfoData(temphandle,dimbuf,256,DTAG_NAME,0);
  427.             }
  428.             if (a && (((struct NameInfo *)dimbuf)->Name)) {
  429.                 strcpy(iffscreenname,((struct NameInfo *)dimbuf)->Name);
  430.                 if ((ptr=strchr(iffscreenname,':'))) strcpy(iffscreenname,ptr+1);
  431.             }
  432.             GetDisplayInfoData(handle,dimbuf,256,DTAG_DIMS,0);
  433.             dimension=(struct DimensionInfo *)dimbuf;
  434.             maxwidth=(dimension->StdOScan.MaxX-dimension->StdOScan.MinX)+1;
  435.             maxheight=(dimension->StdOScan.MaxY-dimension->StdOScan.MinY)+1;
  436.             if (depth>dimension->MaxDepth) {
  437.                 retcode=IFFERR_BADMODE;
  438.                 goto endiff;
  439.             }
  440.         }
  441.         else extflag=0;
  442.         viewflags=0;
  443.         if ((viewmode&SUPER_KEY)==SUPER_KEY) viewflags|=SUPERHIRES|HIRES;
  444.         else if (viewmode&HIRES_KEY) viewflags|=HIRES;
  445.         if (viewmode&LORESLACE_KEY) viewflags|=LACE;
  446.         if (viewmode&HAM_KEY) viewflags|=HAM;
  447.         if (viewmode&EXTRAHALFBRITE_KEY) viewflags|=EXTRA_HALFBRITE;
  448.         if (!extflag) viewmode=viewflags;
  449.     }
  450.  
  451.     if (!extflag) {
  452.         viewmode&=0x0000ffff;
  453.         viewmode&=~(SPRITES|GENLOCK_AUDIO|GENLOCK_VIDEO|VP_HIDE|DUALPF|PFBA|EXTENDED_MODE);
  454.         viewflags=viewmode;
  455.  
  456.         if (viewflags&HIRES) {
  457.             if (viewflags&SUPERHIRES) maxwidth*=4;
  458.             else maxwidth*=2;
  459.             minwidth*=2;
  460.         }
  461.     }
  462.  
  463.     if (screenwidth<minwidth) screenwidth=minwidth;
  464.     else if (screenwidth>maxwidth) screenwidth=maxwidth;
  465.  
  466.     if (!extflag && viewflags&LACE) {
  467.         maxheight*=2;
  468.         minheight*=2;
  469.     }
  470.     if (screenheight<minheight) screenheight=minheight;
  471.     else if (screenheight>maxheight) screenheight=maxheight;
  472.  
  473.     if (imagewidth<screenwidth) bitmapwidth=screenwidth;
  474.     else bitmapwidth=imagewidth;
  475.     if (imageheight<screenheight) bitmapheight=screenheight;
  476.     else bitmapheight=imageheight;
  477.  
  478.     if (bitmapwidth>screenwidth || bitmapheight>screenheight) scroll=3;
  479.     dotitle();
  480.  
  481.     if (isanim && first_anim_frame) {
  482.         if (!(animframe_bm[0]=getbitmap(bitmapwidth,bitmapheight,bmhead.nPlanes))) {
  483.             retcode=IFFERR_NOMEM;
  484.             goto endiff;
  485.         }
  486.         if (doublebuffer) {
  487.             if ((animframe_bm[1]=getbitmap(bitmapwidth,bitmapheight,bmhead.nPlanes))) {
  488.                 initialframe_bm=getbitmap(bitmapwidth,bitmapheight,bmhead.nPlanes);
  489. #ifdef DO_DBUF
  490.                 if (system_version2>=OSVER_39 &&
  491.                     (dbufinfo=AllocDBufInfo(ivp))) {
  492.                     if (dbufport=LCreatePort(NULL,0)) {
  493.                         dbufinfo->dbi_SafeMessage.mn_ReplyPort=dbufport;
  494.                         dbufinfo->dbi_SafeMessage.mn_Length=sizeof(struct Message);
  495.                     }
  496.                 }
  497. #endif
  498.             }
  499.         }
  500.     }
  501.  
  502.     if (doublebuffer) {
  503.         for (a=0;a<2;a++) {
  504.             if (animframe_bm[a]) {
  505.                 if (!(iffbm[a]=LAllocRemember(&iffkey,sizeof(struct BitMap),MEMF_CLEAR))) {
  506.                     retcode=IFFERR_NOMEMORY;
  507.                     goto endiff;
  508.                 }
  509.                 CopyMem((char *)animframe_bm[a],(char *)iffbm[a],sizeof(struct BitMap));
  510.             }
  511.         }
  512.     }
  513.     else if (!(iffbm[0]=getbitmap(bitmapwidth,bitmapheight,depth))) {
  514.         retcode=IFFERR_NOMEMORY;
  515.         goto endiff;
  516.     }
  517.  
  518.     if (system_version2) {
  519.         struct TagItem iffscr_tags[10];
  520.         ULONG err=0;
  521.  
  522.         iffscr_tags[0].ti_Tag=SA_Width;
  523.         iffscr_tags[0].ti_Data=bitmapwidth;
  524.         iffscr_tags[1].ti_Tag=SA_Height;
  525.         iffscr_tags[1].ti_Data=bitmapheight;
  526.         iffscr_tags[2].ti_Tag=SA_Depth;
  527.         iffscr_tags[2].ti_Data=depth;
  528.         iffscr_tags[3].ti_Tag=SA_BitMap;
  529.         iffscr_tags[3].ti_Data=(ULONG)iffbm[0];
  530.         iffscr_tags[4].ti_Tag=SA_Behind;
  531.         iffscr_tags[4].ti_Data=TRUE;
  532.         iffscr_tags[5].ti_Tag=SA_DisplayID;
  533.         iffscr_tags[5].ti_Data=viewmode;
  534.         iffscr_tags[6].ti_Tag=SA_AutoScroll;
  535.         iffscr_tags[6].ti_Data=TRUE;
  536.         iffscr_tags[7].ti_Tag=SA_Overscan;
  537.         iffscr_tags[7].ti_Data=OSCAN_MAX;
  538.         iffscr_tags[8].ti_Tag=SA_ErrorCode;
  539.         iffscr_tags[8].ti_Data=(ULONG)&err;
  540.         iffscr_tags[9].ti_Tag=TAG_END;
  541.         iffscr_tags[9].ti_Data=0;
  542.  
  543.         iffscreen=OpenScreenTagList(NULL,iffscr_tags);
  544.     }
  545.     else {
  546.         struct NewScreen iffscr;
  547.  
  548.         iffscr.LeftEdge=0;
  549.         iffscr.TopEdge=0;
  550.         iffscr.Width=screenwidth;
  551.         iffscr.Height=screenheight;
  552.         iffscr.Depth=depth;
  553.         iffscr.DetailPen=0;
  554.         iffscr.BlockPen=0;
  555.         iffscr.ViewModes=viewflags;
  556.         iffscr.Type=CUSTOMSCREEN|SCREENBEHIND|CUSTOMBITMAP;
  557.         iffscr.Font=NULL;
  558.         iffscr.DefaultTitle=NULL;
  559.         iffscr.Gadgets=NULL;
  560.         iffscr.CustomBitMap=iffbm[0];
  561.  
  562.         iffscreen=OpenScreen(&iffscr);
  563.     }
  564.  
  565.     if (!iffscreen) {
  566.         retcode=IFFERR_NOSCREEN;
  567.         goto endiff;
  568.     }
  569.  
  570.     ivp=&(iffscreen->ViewPort);
  571.     LoadRGB4(ivp,nullpalette,1<<depth);
  572.  
  573.     iffwin.Screen=iffscreen;
  574.     iffwin.Width=iffscreen->Width;
  575.     iffwin.Height=iffscreen->Height;
  576.  
  577.     if (!(iffwindow=OpenWindow(&iffwin))) {
  578.         retcode=IFFERR_NOSCREEN;
  579.         goto endiff;
  580.     }
  581.  
  582.     setnullpointer(iffwindow);
  583.  
  584.     if (isanim && first_anim_frame) {
  585.         framenum=1;
  586.         framedisp=animrestart=0;
  587.         current_anim_frame=first_anim_frame;
  588.  
  589.         rletobuffer(bodyptr,bmhead.w,bmhead.h,animframe_bm[0],bmhead.masking,bmhead.compression);
  590.  
  591.         if (doublebuffer) {
  592.             if (animframe_bm[1]) {
  593.                 BltBitMap(animframe_bm[0],0,0,animframe_bm[1],0,0,bmhead.w,bmhead.h,0xc0,0xff,NULL);
  594.                 if (initialframe_bm)
  595.                     BltBitMap(animframe_bm[0],0,0,initialframe_bm,0,0,bmhead.w,bmhead.h,0xc0,0xff,NULL);
  596.                 WaitBlit();
  597.             }
  598.         }
  599.         else {
  600.             animframeimage.LeftEdge=(bitmapwidth-bmhead.w)/2;
  601.             animframeimage.TopEdge=(bitmapheight-bmhead.h)/2;
  602.             doanimframe();
  603.         }
  604.     }
  605.     else readpic(&bmhead,bodyptr,iffbm[0]);
  606.  
  607.     if (numcolours>ivp->ColorMap->Count) numcolours=ivp->ColorMap->Count;
  608.  
  609.     if (!copperlist) {
  610.         if (!system_version2) {
  611.             int x,y;
  612.  
  613.             if (viewflags&HIRES) x=(scrdata_norm_width-screenwidth)/2;
  614.             else x=((scrdata_norm_width/2)-screenwidth)/2;
  615.             if (viewflags&LACE) y=((scrdata_norm_height*2)-screenheight)/2;
  616.             else y=(scrdata_norm_height-screenheight)/2;
  617.             ivp->DxOffset=x;
  618.             ivp->DyOffset=y;
  619.             MakeScreen(iffscreen);
  620.         }
  621.         if (viewflags&HAM || pchghead) {
  622.             if (palette32) LoadRGB32(ivp,colourtable_8);
  623.             else LoadRGB4(ivp,colourtable_4,numcolours);
  624.         }
  625.     }
  626.  
  627.     if (pchghead) {
  628.         if (sham) PCHG_SetUserCopList(0,0,ivp,pchghead,&pchghead[1],sham);
  629.         else PCHG_ParsePCHG(pchghead,ivp);
  630.     }
  631.  
  632.     ActivateWindow(iffwindow);
  633.     ScreenToFront(iffscreen);
  634.  
  635.     if (copperlist) {
  636.         view=ViewAddress();
  637.         if ((copperheight>>1)>scrdata_norm_height) view->DyOffset=14+(system_version2?8:0);
  638.         if (mp) LoadRGB4(ivp,colourlist,4);
  639.         if (!InitDHIRES(mp)) {
  640.             retcode=IFFERR_NOMEMORY;
  641.             goto endiff;
  642.         }
  643.     }
  644.     else if (!specialformat && !(viewflags&HAM)) {
  645.         if (palette32) FadeRGB32(iffscreen,&colourtable_8[1],numcolours,1,config->fadetime);
  646.         else FadeRGB4(iffscreen,colourtable_4,numcolours,1,config->fadetime);
  647.     }
  648.  
  649.     if (currange) initcycle(ivp,colourtable_4,numcolours,cyclerange,currange);
  650.  
  651.     if (!(a=WaitForMouseClick(scroll,iffwindow))) retcode=1;
  652.     else retcode=-1;
  653.  
  654.     if (checkcycling()) togglecycle();
  655.     stopcycle();
  656.  
  657.     if (specialformat) {
  658.         ScreenToBack(iffscreen);
  659.         FreeVPortCopLists(ivp);
  660.     }
  661.     else if (a!=-3 && !(viewflags&HAM)) {
  662.         if (palette32) FadeRGB32(iffscreen,&colourtable_8[1],numcolours,-1,config->fadetime);
  663.         else FadeRGB4(iffscreen,colourtable_4,numcolours,-1,config->fadetime);
  664.     }
  665.     
  666. endiff:
  667. #ifdef DO_DBUF
  668.     if (dbufinfo) FreeDBufInfo(dbufinfo);
  669.     if (dbufport) LDeletePort(dbufport);
  670. #endif
  671.     cleanupbitmap();
  672.     ActivateWindow(Window);
  673.     if (pchghead && sham) {
  674.         FreeMem(pchghead,sizeof(struct PCHGHeader)+((pchghead->LineCount+31)/32)*4);
  675.     }
  676.     LFreeRemember(&iffkey);
  677.     if (picbuffer) FreeMem(picbuffer,buffersize);
  678.     first_anim_frame=NULL;
  679.     colourtable_8=NULL; colourtable_4=NULL;
  680.     return(retcode);
  681. }
  682.  
  683. struct BitMap *getbitmap(width,height,depth)
  684. int width,height,depth;
  685. {
  686.     struct BitMap *bm;
  687.     int a;
  688.  
  689.     if (system_version2>=OSVER_39) {
  690.         return((AllocBitMap(width,height,depth,BMF_DISPLAYABLE|BMF_CLEAR,NULL)));
  691.     }
  692.     if (!(bm=AllocMem(sizeof(struct BitMap),MEMF_CLEAR))) return(NULL);
  693.     InitBitMap(bm,depth,width,height);
  694.     for (a=0;a<8;a++) bm->Planes[a]=NULL;
  695.     for (a=0;a<depth;a++) {
  696.         if (!(bm->Planes[a]=AllocRaster(width,height))) {
  697.             freebitmap(bm,width,height);
  698.             return(NULL);
  699.         }
  700.     }
  701.     return(bm);
  702. }
  703.  
  704. void freebitmap(bm,width,height)
  705. struct BitMap *bm;
  706. {
  707.     int a;
  708.  
  709.     if (bm) {
  710.         if (system_version2>=OSVER_39) FreeBitMap(bm);
  711.         else {
  712.             for (a=0;a<8;a++) if (bm->Planes[a]) FreeRaster(bm->Planes[a],width,height);
  713.             FreeMem(bm,sizeof(struct BitMap));
  714.         }
  715.     }
  716. }
  717.  
  718. void cleanupbitmap()
  719. {
  720.     int num;
  721.  
  722.     if (blankscreen) ScreenToFront(blankscreen);
  723.     else ScreenToFront(Window->WScreen);
  724.     if (iffwindow) {
  725.         CloseWindow(iffwindow);
  726.         iffwindow=NULL;
  727.     }
  728.     if (iffscreen) {
  729.         CloseScreen(iffscreen);
  730.         iffscreen=NULL;
  731.     }
  732.     if (iffbm[0] && !doublebuffer) freebitmap(iffbm[0],bitmapwidth,bitmapheight);
  733.     for (num=0;num<2;num++) {
  734.         if (animframe_bm[num]) freebitmap(animframe_bm[num],bitmapwidth,bitmapheight);
  735.     }
  736.     if (initialframe_bm) freebitmap(initialframe_bm,bitmapwidth,bitmapheight);
  737. }
  738.  
  739. void rletobuffer(source,sourcewidth,sourceheight,dest,mask,comp)
  740. unsigned char *source;
  741. int sourcewidth,sourceheight;
  742. struct BitMap *dest;
  743. char mask,comp;
  744. {
  745.     struct RLEinfo picinfo;
  746.  
  747.     picinfo.sourceptr=source;
  748.     picinfo.destplanes=dest->Planes;
  749.     picinfo.imagebpr=((sourcewidth+15)/16)*2;
  750.     picinfo.imageheight=sourceheight;
  751.     picinfo.imagedepth=dest->Depth;
  752.     picinfo.destbpr=dest->BytesPerRow;
  753.     picinfo.destheight=dest->Rows;
  754.     picinfo.destdepth=dest->Depth;
  755.     picinfo.masking=mask;
  756.     picinfo.compression=comp;
  757.     picinfo.offset=0;
  758.  
  759.     decoderle(&picinfo);
  760. }
  761.  
  762. void readpic(bmhead,source,bmap)
  763. BitMapHeader *bmhead;
  764. unsigned char *source;
  765. struct BitMap *bmap;
  766. {
  767.     int rowbytes,bmrbytes,rows;
  768.     int byteoff=0;
  769.     struct RLEinfo picinfo;
  770.  
  771.     rowbytes=((bmhead->w+15)/16)*2;
  772.     if (system_version2>=OSVER_39) bmrbytes=((GetBitMapAttr(bmap,BMA_WIDTH)+15)/16)*2;
  773.     else bmrbytes=bmap->BytesPerRow;
  774.  
  775.     if ((rows=bmhead->h)>bmap->Rows) rows=bmap->Rows;
  776.  
  777.     if (!system_version2) {
  778.         if (rowbytes<bmrbytes) byteoff=(bmrbytes-rowbytes)/2;
  779.         else byteoff=0;
  780.         if (rows<bmap->Rows) byteoff+=((bmap->Rows-rows)/2)*bmrbytes;
  781.     }
  782.  
  783.     picinfo.sourceptr=source;
  784.     picinfo.destplanes=bmap->Planes;
  785.     picinfo.imagebpr=rowbytes;
  786.     picinfo.imageheight=rows;
  787.     picinfo.imagedepth=bmhead->nPlanes;
  788.     picinfo.destbpr=bmrbytes;
  789.     picinfo.destheight=bmap->Rows;
  790.     picinfo.destdepth=bmap->Depth;
  791.     picinfo.masking=bmhead->masking;
  792.     picinfo.compression=bmhead->compression;
  793.     picinfo.offset=byteoff;
  794.  
  795.     decoderle(&picinfo);
  796. }
  797.  
  798. void decoderle(rleinfo)
  799. struct RLEinfo *rleinfo;
  800. {
  801.     register char *source,*dest;
  802.     register int copy,col;
  803.     register char count;
  804.     int plane,row,bmoffset,planes;
  805.  
  806.     planes=rleinfo->imagedepth;
  807.     if (rleinfo->masking==1) ++planes;
  808.     source=rleinfo->sourceptr;
  809.  
  810.     switch (rleinfo->compression) {
  811.         case 1:
  812.             bmoffset=rleinfo->offset;
  813.             for (row=0;row<rleinfo->imageheight;row++) {
  814.                 for (plane=0;plane<planes;plane++) {
  815.                     if (plane<rleinfo->destdepth && rleinfo->destplanes[plane])
  816.                         dest=(char *)(rleinfo->destplanes[plane]+bmoffset);
  817.                     else dest=NULL;
  818.  
  819.                     for (col=0;col<rleinfo->imagebpr;) {
  820.                         if ((count=*source++)>=0) {
  821.                             copy=count+1;
  822.                             col+=copy;
  823.                             if (dest) {
  824.                                 while (copy--) *dest++=*source++;
  825.                             }
  826.                             else source+=copy;
  827.                         }
  828.                         else if (count!=-128) {
  829.                             copy=1-count;
  830.                             col+=copy;
  831.                             if (dest) {
  832.                                 while (copy--) *dest++=*source;
  833.                             }
  834.                             ++source;
  835.                         }
  836.                     }
  837.                 }
  838.                 bmoffset+=rleinfo->destbpr;
  839.             }
  840.             break;
  841.         case 0:
  842.             bmoffset=rleinfo->offset;
  843.             for (row=0;row<rleinfo->imageheight;row++) {
  844.                 for (plane=0;plane<planes;plane++) {
  845.                     if (plane<rleinfo->destdepth)
  846.                         CopyMem(source,(char *)rleinfo->destplanes[plane]+bmoffset,rleinfo->imagebpr);
  847.                     source+=rleinfo->imagebpr;
  848.                 }
  849.                 bmoffset+=rleinfo->destbpr;
  850.             }
  851.             break;
  852.     }
  853. }
  854.  
  855. void doanimframe()
  856. {
  857.     struct AnimFrame *frame;
  858.  
  859.     if (last_anim_frame) {
  860.         frame=last_anim_frame;
  861.         last_anim_frame=last_anim_frame->next;
  862.     }
  863.     else {
  864.         frame=&initial_anim_cmap;
  865.         last_anim_frame=first_anim_frame;
  866.     }
  867.  
  868.     if (frame->cmap) {
  869.         build_palettes(frame->cmap,frame->cmapsize,colourtable_4,colourtable_8);
  870.         if (palette32) LoadRGB32(ivp,colourtable_8);
  871.         else LoadRGB4(ivp,colourtable_4,numcolours);
  872.     }
  873.  
  874.     if (doublebuffer && iffbm[1]) {
  875. #ifdef DO_DBUF
  876.         if (dbufport) {
  877.             ChangeVPBitMap(ivp,iffbm[framedisp],dbufinfo);
  878.             WaitPort(dbufport);
  879.             GetMsg(dbufport);
  880.         }
  881.         else {
  882.             iffscreen->RastPort.BitMap=iffbm[framedisp];
  883.             iffscreen->ViewPort.RasInfo->BitMap=iffbm[framedisp];
  884.             MakeScreen(iffscreen);
  885.             RethinkDisplay();
  886.         }
  887. #else
  888.         iffscreen->RastPort.BitMap=iffbm[framedisp];
  889.         iffscreen->ViewPort.RasInfo->BitMap=iffbm[framedisp];
  890.         MakeScreen(iffscreen);
  891.         RethinkDisplay();
  892. #endif
  893.     }
  894.     else {
  895.         BltBitMap(animframe_bm[framedisp],0,0,
  896.             iffwindow->RPort->BitMap,animframeimage.LeftEdge,animframeimage.TopEdge,
  897.             bmhead.w,bmhead.h,0xc0,0xff,NULL);
  898.         WaitBlit();
  899.     }
  900.     if (animframe_bm[1]) framedisp=1-framedisp;
  901.  
  902.     if (!current_anim_frame) {
  903.         if (animframe_bm[1]) {
  904.             if (initialframe_bm) {
  905.                 BltBitMap(initialframe_bm,0,0,
  906.                     animframe_bm[framedisp],0,0,
  907.                     bmhead.w,bmhead.h,0xc0,0xff,NULL);
  908.                 WaitBlit();
  909.             }
  910.             else rletobuffer(bodyptr,bmhead.w,bmhead.h,
  911.                 animframe_bm[framedisp],bmhead.masking,bmhead.compression);
  912.         }
  913.         if (got_dpan || framenum==0) {
  914.             current_anim_frame=first_anim_frame;
  915.             last_anim_frame=first_anim_frame;
  916.             framenum=1;
  917.         }
  918.         else framenum=0;
  919.     }
  920.  
  921.     if (framenum>0) {
  922.         switch (current_anim_frame->animheader->operation) {
  923.             case 0:
  924.                 if (current_anim_frame->delta)
  925.                     rletobuffer(current_anim_frame->delta,bmhead.w,bmhead.h,
  926.                         animframe_bm[framedisp],bmhead.masking,bmhead.compression);
  927.                 break;
  928.             case 5:
  929.                 doriff(current_anim_frame->delta,animframe_bm[framedisp],
  930.                     (current_anim_frame->animheader->bits&2 || !animframe_bm[1]),bmhead.w,0);
  931.                 break;
  932.             case 7:
  933.                 doriff7(current_anim_frame->delta,animframe_bm[framedisp],
  934.                     bmhead.w,(current_anim_frame->animheader->bits&1)?2:1);
  935.                 break;
  936.             case 8:
  937.                 doriff(current_anim_frame->delta,animframe_bm[framedisp],
  938.                     1,bmhead.w,(current_anim_frame->animheader->bits&1)?2:1);
  939.                 break;
  940.         }
  941.         ++framenum;
  942.         current_anim_frame=current_anim_frame->next;
  943.     }
  944. }
  945.  
  946. void doriff(delta,image,xor,sourcewidth,size)
  947. unsigned char *delta;
  948. struct BitMap *image;
  949. int xor,sourcewidth,size;
  950. {
  951.     int plane,*dptr;
  952.     unsigned char *data;
  953.  
  954.     sourcewidth=((sourcewidth+15)/16)*2;
  955.  
  956.     if ((dptr=(int *)delta)) {
  957.         for (plane=0;plane<image->Depth;plane++) {
  958.             if (dptr[plane]) {
  959.                 data=(unsigned char *)delta+dptr[plane];
  960.                 if (size==0) {
  961.                     if (xor) decode_riff_xor(data,image->Planes[plane],image->BytesPerRow,sourcewidth);
  962.                     else decode_riff_set(data,image->Planes[plane],image->BytesPerRow,sourcewidth);
  963.                 }
  964.                 else if (size==1)
  965.                     decode_riff_short((USHORT *)data,image->Planes[plane],image->BytesPerRow,sourcewidth);
  966.                 else decode_riff_long((ULONG *)data,image->Planes[plane],image->BytesPerRow,sourcewidth);
  967.             }
  968.         }
  969.     }
  970. }
  971.  
  972. void doriff7(delta,image,sourcewidth,size)
  973. unsigned char *delta;
  974. struct BitMap *image;
  975. int sourcewidth,size;
  976. {
  977.     int plane,*dptr;
  978.     unsigned char *data;
  979.     unsigned char *opcode;
  980.  
  981.     sourcewidth=((sourcewidth+15)/16)*2;
  982.  
  983.     if ((dptr=(int *)delta)) {
  984.         for (plane=0;plane<image->Depth;plane++) {
  985.             if (dptr[plane] && dptr[plane+8]) {
  986.                 opcode=(unsigned char *)delta+dptr[plane];
  987.                 data=(unsigned char *)delta+dptr[plane+8];
  988.                 if (size==1)
  989.                     decode_riff7_short((USHORT *)data,opcode,image->Planes[plane],image->BytesPerRow,sourcewidth);
  990.                 else decode_riff7_long((ULONG *)data,opcode,image->Planes[plane],image->BytesPerRow,sourcewidth);
  991.             }
  992.         }
  993.     }
  994. }
  995.  
  996. void decode_riff_xor(delta,image,rowbytes,sourcebytes)
  997. unsigned char *delta;
  998. char *image;
  999. int rowbytes,sourcebytes;
  1000. {
  1001.     int column,opcount;
  1002.     unsigned char *data,ch;
  1003.  
  1004.     for (column=0;column<sourcebytes;column++) {
  1005.         data=image+column;
  1006.         opcount=*delta++;
  1007.         while (opcount--) {
  1008.             ch=*delta++;
  1009.             if (ch) {
  1010.                 if (!(ch&128)) data+=rowbytes*ch;
  1011.                 else {
  1012.                     ch&=127;
  1013.                     while (ch--) {
  1014.                         *data^=*delta++;
  1015.                         data+=rowbytes;
  1016.                     }
  1017.                 }
  1018.             }
  1019.             else {
  1020.                 ch=*delta++;
  1021.                 while (ch--) {
  1022.                     *data^=*delta;
  1023.                     data+=rowbytes;
  1024.                 }
  1025.                 ++delta;
  1026.             }
  1027.         }
  1028.     }
  1029. }
  1030.  
  1031. void decode_riff_set(delta,image,rowbytes,sourcebytes)
  1032. unsigned char *delta;
  1033. char *image;
  1034. int rowbytes,sourcebytes;
  1035. {
  1036.     int column,opcount;
  1037.     unsigned char *data,ch;
  1038.  
  1039.     for (column=0;column<sourcebytes;column++) {
  1040.         data=image+column;
  1041.         opcount=*delta++;
  1042.         while (opcount--) {
  1043.             ch=*delta++;
  1044.             if (ch) {
  1045.                 if (!(ch&128)) data+=rowbytes*ch;
  1046.                 else {
  1047.                     ch&=127;
  1048.                     while (ch--) {
  1049.                         *data=*delta++;
  1050.                         data+=rowbytes;
  1051.                     }
  1052.                 }
  1053.             }
  1054.             else {
  1055.                 ch=*delta++;
  1056.                 while (ch--) {
  1057.                     *data=*delta;
  1058.                     data+=rowbytes;
  1059.                 }
  1060.                 ++delta;
  1061.             }
  1062.         }
  1063.     }
  1064. }
  1065.  
  1066. void decode_riff_short(delta,image,rowbytes,sourcebytes)
  1067. USHORT *delta;
  1068. unsigned char *image;
  1069. int rowbytes,sourcebytes;
  1070. {
  1071.     int column,opcount;
  1072.     unsigned char *data;
  1073.     USHORT ch;
  1074.  
  1075.     sourcebytes/=2;
  1076.  
  1077.     for (column=0;column<sourcebytes;column++) {
  1078.         data=(unsigned char *)(image+(column*2));
  1079.         opcount=*delta++;
  1080.         while (opcount--) {
  1081.             ch=*delta++;
  1082.             if (ch) {
  1083.                 if (!(ch&0x8000)) data+=rowbytes*ch;
  1084.                 else {
  1085.                     ch&=0x7fff;
  1086.                     while (ch--) {
  1087.                         *(USHORT *)data=*delta++;
  1088.                         data+=rowbytes;
  1089.                     }
  1090.                 }
  1091.             }
  1092.             else {
  1093.                 ch=*delta++;
  1094.                 while (ch--) {
  1095.                     *(USHORT *)data=*delta;
  1096.                     data+=rowbytes;
  1097.                 }
  1098.                 ++delta;
  1099.             }
  1100.         }
  1101.     }
  1102. }
  1103.  
  1104. void decode_riff_long(delta,image,rowbytes,sourcebytes)
  1105. ULONG *delta;
  1106. unsigned char *image;
  1107. int rowbytes,sourcebytes;
  1108. {
  1109.     int column,opcount;
  1110.     unsigned char *data;
  1111.     ULONG ch;
  1112.  
  1113.     sourcebytes/=4;
  1114.  
  1115.     for (column=0;column<sourcebytes;column++) {
  1116.         data=(unsigned char *)(image+(column*4));
  1117.         opcount=*delta++;
  1118.         while (opcount--) {
  1119.             ch=*delta++;
  1120.             if (ch) {
  1121.                 if (!(ch&0x80000000)) data+=rowbytes*ch;
  1122.                 else {
  1123.                     ch&=0x7fffffff;
  1124.                     while (ch--) {
  1125.                         *(ULONG *)data=*delta++;
  1126.                         data+=rowbytes;
  1127.                     }
  1128.                 }
  1129.             }
  1130.             else {
  1131.                 ch=*delta++;
  1132.                 while (ch--) {
  1133.                     *(ULONG *)data=*delta;
  1134.                     data+=rowbytes;
  1135.                 }
  1136.                 ++delta;
  1137.             }
  1138.         }
  1139.     }
  1140. }
  1141.  
  1142. void decode_riff7_short(delta,opcode,image,rowbytes,sourcebytes)
  1143. USHORT *delta;
  1144. unsigned char *opcode;
  1145. unsigned char *image;
  1146. int rowbytes,sourcebytes;
  1147. {
  1148.     int column,opcount;
  1149.     unsigned char *data,ch;
  1150.  
  1151.     sourcebytes/=2;
  1152.  
  1153.     for (column=0;column<sourcebytes;column++) {
  1154.         data=(unsigned char *)(image+(column*2));
  1155.         opcount=*opcode++;
  1156.         while (opcount--) {
  1157.             ch=*opcode++;
  1158.             if (ch) {
  1159.                 if (!(ch&0x80)) data+=rowbytes*ch;
  1160.                 else {
  1161.                     ch&=0x7f;
  1162.                     while (ch--) {
  1163.                         *(USHORT *)data=*delta++;
  1164.                         data+=rowbytes;
  1165.                     }
  1166.                 }
  1167.             }
  1168.             else {
  1169.                 ch=*opcode++;
  1170.                 while (ch--) {
  1171.                     *(USHORT *)data=*delta;
  1172.                     data+=rowbytes;
  1173.                 }
  1174.                 ++delta;
  1175.             }
  1176.         }
  1177.     }
  1178. }
  1179.  
  1180. void decode_riff7_long(delta,opcode,image,rowbytes,sourcebytes)
  1181. ULONG *delta;
  1182. unsigned char *opcode;
  1183. unsigned char *image;
  1184. int rowbytes,sourcebytes;
  1185. {
  1186.     int column,opcount;
  1187.     unsigned char *data,ch;
  1188.  
  1189.     sourcebytes/=4;
  1190.  
  1191.     for (column=0;column<sourcebytes;column++) {
  1192.         data=(unsigned char *)(image+(column*4));
  1193.         opcount=*opcode++;
  1194.         while (opcount--) {
  1195.             ch=*opcode++;
  1196.             if (ch) {
  1197.                 if (!(ch&0x80)) data+=rowbytes*ch;
  1198.                 else {
  1199.                     ch&=0x7f;
  1200.                     while (ch--) {
  1201.                         *(ULONG *)data=*delta++;
  1202.                         data+=rowbytes;
  1203.                     }
  1204.                 }
  1205.             }
  1206.             else {
  1207.                 ch=*opcode++;
  1208.                 while (ch--) {
  1209.                     *(ULONG *)data=*delta;
  1210.                     data+=rowbytes;
  1211.                 }
  1212.                 ++delta;
  1213.             }
  1214.         }
  1215.     }
  1216. }
  1217.  
  1218. WaitForMouseClick(tits,wind)
  1219. int tits;
  1220. struct Window *wind;
  1221. {
  1222.     struct IntuiMessage *msg;
  1223.     ULONG class;
  1224.     USHORT code,qual;
  1225.     int ticks,waitfor=0,pon=0,waitbits,retcode=1,gottimer=0,origspeed,anim,delta;
  1226.     struct timerequest treq;
  1227.  
  1228.     while (msg=(struct IntuiMessage *) GetMsg(wind->UserPort))
  1229.         ReplyMsg((struct Message *)msg);
  1230.     if (!first_anim_frame && config->showdelay>0) {
  1231.         waitfor=config->showdelay*10; ticks=0;
  1232.     }
  1233.  
  1234.     origspeed=animspeed;
  1235.  
  1236.     waitbits=1<<wind->UserPort->mp_SigBit;
  1237.     if (first_anim_frame) {
  1238.         if (!(OpenDevice(TIMERNAME,UNIT_VBLANK,&treq.tr_node,0))) {
  1239.             treq.tr_node.io_Message.mn_ReplyPort=general_port;
  1240.             treq.tr_node.io_Command=TR_ADDREQUEST;
  1241.             treq.tr_node.io_Flags=0;
  1242.             treq.tr_time.tv_secs=0;
  1243.             treq.tr_time.tv_micro=10;
  1244.             SendIO(&treq.tr_node);
  1245.             waitbits|=1<<general_port->mp_SigBit;
  1246.             gottimer=1;
  1247.         }
  1248.         if (!(anim=(!(config->viewbits&VIEWBITS_PAUSEANIMS))) && doublebuffer)
  1249.             doanimframe();
  1250.     }
  1251.  
  1252.     FOREVER {
  1253.         if (first_anim_frame) {
  1254.             while (GetMsg(general_port));
  1255.             if (CheckIO(&treq.tr_node)) {
  1256.                 WaitIO(&treq.tr_node);
  1257.                 treq.tr_time.tv_secs=0;
  1258.                 treq.tr_time.tv_micro=animspeed;
  1259.                 SendIO(&treq.tr_node);
  1260.                 if (anim) doanimframe();
  1261.             }
  1262.         }
  1263.         while (msg=(struct IntuiMessage *) GetMsg(wind->UserPort)) {
  1264.             class=msg->Class; code=msg->Code; qual=msg->Qualifier;
  1265.             ReplyMsg((struct Message *) msg);
  1266.             switch (class) {
  1267.                 case IDCMP_INTUITICKS:
  1268.                     if (waitfor && (++ticks)>=waitfor) retcode=0;
  1269.                     break;
  1270.                 case IDCMP_RAWKEY:
  1271.                     if (code>=0x50 && code<=0x59) {
  1272.                         code-=0x50;
  1273.                         animspeed=(code*10000)+10;
  1274.                         break;
  1275.                     }
  1276.                     switch (code) {
  1277.                         case 0x0b:
  1278.                             if ((animspeed+=10000)>1000000) animspeed=1000000;
  1279.                             break;
  1280.                         case 0x0c:
  1281.                             if ((animspeed-=10000)<10) animspeed=10;
  1282.                             break;
  1283.                         case 0x0d:
  1284.                             animspeed=origspeed;
  1285.                             break;
  1286.                         case 0x21:
  1287.                             anim=1-anim;
  1288.                             break;
  1289.                         case 0x36:
  1290.                             if (first_anim_frame) {
  1291.                                 anim=0;
  1292.                                 doanimframe();
  1293.                             }
  1294.                             break;
  1295.                         case CURSOR_LEFT:
  1296.                         case 0x2d:
  1297.                         case CURSOR_RIGHT:
  1298.                         case 0x2f:
  1299.                             if (tits!=3) break;
  1300.                             if (qual&IEQUALIFIER_CONTROL) delta=-bitmapwidth;
  1301.                             else if (qual&IEQUALIFIER_ANYSHIFT) delta=-(screenwidth-20);
  1302.                             else delta=-2;
  1303.                             if (code==CURSOR_RIGHT || code==0x2f) delta=-delta;
  1304.                             if (system_version2) MoveScreen(wind->WScreen,-delta,0);
  1305.                             else {
  1306.                                 ivp->RasInfo->RxOffset+=delta;
  1307.                                 docheckrasscroll(wind->WScreen);
  1308.                             }
  1309.                             break;
  1310.                         case CURSOR_UP:
  1311.                         case 0x3e:
  1312.                         case CURSOR_DOWN:
  1313.                         case 0x1e:
  1314.                             if (tits!=3) break;
  1315.                             if (qual&IEQUALIFIER_CONTROL) delta=bitmapheight;
  1316.                             else if (qual&IEQUALIFIER_ANYSHIFT) delta=screenheight-20;
  1317.                             else delta=2;
  1318.                             if (code==CURSOR_UP || code==0x3e) {
  1319.                                 delta=-delta;
  1320.                                 if (system_version2) {
  1321.                                     if (wind->WScreen->TopEdge-delta>0)
  1322.                                         delta=wind->WScreen->TopEdge;
  1323.                                 }
  1324.                             }
  1325.                             if (system_version2) MoveScreen(wind->WScreen,0,-delta);
  1326.                             else {
  1327.                                 ivp->RasInfo->RyOffset+=delta;
  1328.                                 docheckrasscroll(wind->WScreen);
  1329.                             }
  1330.                             break;
  1331.                         case 0x44:
  1332.                             if (tits==2) retcode=-2;
  1333.                             else retcode=0;
  1334.                             break;
  1335.                         case 0x45:
  1336.                             retcode=-1;
  1337.                             break;
  1338.                         case 0x10:
  1339.                             if (!(qual&IEQUALIFIER_REPEAT)) retcode=0;
  1340.                             break;
  1341.                         case 0x42:
  1342.                             if (tits&1 && currange) togglecycle();
  1343.                             break;
  1344.                         case 0x5f:
  1345.                         case 0x19:
  1346.                         case 0x40:
  1347.                             if (!(qual&IEQUALIFIER_REPEAT)) {
  1348.                                 ModifyIDCMP(wind,(wind->IDCMPFlags&~IDCMP_INACTIVEWINDOW)|IDCMP_ACTIVEWINDOW);
  1349.                                 if (tits&1) gfxprint(wind,&iffscreen->RastPort,0,0,bitmapwidth,bitmapheight,1);
  1350.                                 else gfxprint(wind,wind->RPort,0,0,wind->Width,wind->Height,0);
  1351.                             }
  1352.                             break;
  1353.                         case 0x39:
  1354.                             if (pon) setnullpointer(wind);
  1355.                             else ClearPointer(wind);
  1356.                             pon^=1;
  1357.                             break;
  1358.                         case 0x1a:
  1359.                             if (colourtable_4 && !specialformat)
  1360.                                 LoadRGB4(ivp,colourtable_4,numcolours);
  1361.                             break;
  1362.                         case 0x1b:
  1363.                             if (colourtable_8 && !specialformat)
  1364.                                 LoadRGB32(ivp,colourtable_8);
  1365.                             break;
  1366.                     }
  1367.                     break;
  1368.                 case IDCMP_ACTIVEWINDOW:
  1369.                     ModifyIDCMP(wind,(wind->IDCMPFlags&~IDCMP_ACTIVEWINDOW)|IDCMP_INACTIVEWINDOW);
  1370.                     break;
  1371.                 case IDCMP_INACTIVEWINDOW:
  1372.                     if (IntuitionBase->ActiveScreen!=wind->WScreen) {
  1373.                         retcode=-3;
  1374.                         break;
  1375.                     }
  1376.                     code=SELECTDOWN;
  1377.                 case IDCMP_MOUSEBUTTONS:
  1378.                     if (code==SELECTDOWN) retcode=0;
  1379.                     else if (code==MENUDOWN) retcode=-1;
  1380.                     break;
  1381.             }
  1382.             if (retcode!=1) break;
  1383.         }
  1384.         if (retcode!=1) break;
  1385.         Wait(waitbits);
  1386.     }
  1387.     if (first_anim_frame && gottimer) {
  1388.         if (!(CheckIO(&treq.tr_node)))
  1389.             AbortIO(&treq.tr_node);
  1390.         WaitIO(&treq.tr_node);
  1391.         CloseDevice(&treq.tr_node);
  1392.         while (GetMsg(general_port));
  1393.     }
  1394.     return(retcode);
  1395. }
  1396.  
  1397. chunkread(buf,nbytes)
  1398. void *buf;
  1399. ULONG nbytes;
  1400. {
  1401.     if (bufferpos+nbytes>buffersize) return(0);
  1402.     CopyMem((char *)&picbuffer[bufferpos],(char *)buf,nbytes);
  1403.     bufferpos+=nbytes;
  1404.     return(1);
  1405. }
  1406.  
  1407. void getcolstring(str)
  1408. char *str;
  1409. {
  1410.     if (viewflags&HAM || specialformat) {
  1411.         if (bmhead.nPlanes==8) strcpy(str,"256K");
  1412.         else strcpy(str,"4096");
  1413.     }
  1414.     else lsprintf(str,"%ld",1<<bmhead.nPlanes);
  1415. }
  1416.  
  1417. void dotitle()
  1418. {
  1419.     char title[100],modes[140],cols[30];
  1420.  
  1421.     getcolstring(cols);
  1422.     getviewmodes(modes);
  1423.     lsprintf(title,"%ld x %ld x %ld (page %ld x %ld) %s cols (%s)",
  1424.         bmhead.w,bmhead.h,bmhead.nPlanes,bmhead.pageWidth,bmhead.pageHeight,
  1425.         cols,modes);
  1426.     dostatustext(title);
  1427. }
  1428.  
  1429. void gfxprint(wind,rast,x,y,w,h,iff)
  1430. struct Window *wind;
  1431. struct RastPort *rast;
  1432. int x,y,w,h,iff;
  1433. {
  1434.     struct IntuiMessage *msg;
  1435.     struct Window *pwin;
  1436.     struct Screen *pscr;
  1437.     struct RastPort *prp;
  1438.     ULONG class;
  1439.     USHORT code,gadgetid,qual;
  1440.     struct PrinterData *pd;
  1441.     struct Preferences *prefs;
  1442.     int a,b,abort=0,goff,fnum;
  1443.     char buf[200],modes[140],*ptr,pactcode[6],cols[30],title[120];
  1444.     APTR save;
  1445.     struct DOpusRemember *pkey=NULL;
  1446.     static char firsttime;
  1447.  
  1448.     if (scrdata_is_pal) {
  1449.         printscreen.Height=printwin.Height=256;
  1450.         goff=28;
  1451.     }
  1452.     else {
  1453.         printscreen.Height=printwin.Height=200;
  1454.         goff=0;
  1455.     }
  1456.  
  1457.     for (a=0;a<7;a++) {
  1458.         if (a==5) printgadtxt[a]=globstring[STR_PRINTTITLE];
  1459.         else if (a==6) printgadtxt[a]=globstring[STR_PRINT];
  1460.         else printgadtxt[a]=globstring[STR_ASPECT+a];
  1461.         if (a<6) {
  1462.             for (b=0;;b++) {
  1463.                 if (!printgadtxt[a][b]) break;
  1464.                 if (printgadtxt[a][b]=='_') {
  1465.                     pactcode[a]=tolower(printgadtxt[a][b+1]);
  1466.                     break;
  1467.                 }
  1468.             }
  1469.         }
  1470.     }
  1471.  
  1472.     printgadtxt[7]=str_cancelstring;
  1473.     printgadtxt[8]=NULL;
  1474.     printabortgadtxt[0]=globstring[STR_ABORT_PRINT];
  1475.     for (a=0;a<2;a++) {
  1476.         print_aspect_txt[a]=globstring[STR_PORTRAIT+a];
  1477.         print_image_txt[a]=globstring[STR_POSITIVE+a];
  1478.         print_placement_txt[a]=globstring[STR_CENTER+a];
  1479.     }
  1480.     for (a=0;a<3;a++) print_shade_txt[a]=globstring[STR_BLACK_WHITE+a];
  1481.  
  1482.     if (!(pscr=OpenScreen((struct NewScreen *)&printscreen))) return;
  1483.     LoadRGB4(&(pscr->ViewPort),basepalette,4);
  1484.     printwin.Screen=pscr;
  1485.     if (!(pwin=OpenWindow(&printwin))) {
  1486.         CloseScreen(pscr);
  1487.         return;
  1488.     }
  1489.     prp=pwin->RPort;
  1490.     SetFont(prp,scr_font[FONT_GENERAL]);
  1491.     SetAPen(prp,1);
  1492.     Do3DFrame(prp,0,4+goff,320,88,globstring[STR_DESCRIPTION],2,1);
  1493.     Do3DFrame(prp,0,98+goff,320,86,globstring[STR_PRINT_CONTROL],2,1);
  1494.  
  1495.     if (iff) {
  1496.         ptr=BaseName(picturename);
  1497.         getcolstring(cols);
  1498.         lsprintf(buf,"%12s : %s",
  1499.             globstring[STR_FILE],
  1500.             ptr);
  1501.         iffinfotxt(prp,buf,7,19+goff);
  1502.  
  1503.         lsprintf(buf,"%12s : %ld x %ld",
  1504.             globstring[STR_IMAGE_SIZE],
  1505.             bmhead.w,
  1506.             bmhead.h);
  1507.         iffinfotxt(prp,buf,7,35+goff);
  1508.  
  1509.         if (first_anim_frame) {
  1510.             if (framenum<2) fnum=1;
  1511.             else fnum=framenum-1;
  1512.             lsprintf(buf,"%12s : %ld %s %ld @ %ld/sec",
  1513.                 globstring[STR_NUM_FRAMES],
  1514.                 fnum,
  1515.                 globstring[STR_OF],
  1516.                 framecount+(1-got_dpan),
  1517.                 framespersec);
  1518.             iffinfotxt(prp,buf,7,43+goff);
  1519.  
  1520.             lsprintf(buf,"%12s : ANIM Op %ld",
  1521.                 globstring[STR_ANIM_TYPE],
  1522.                 animtype);
  1523.             iffinfotxt(prp,buf,7,51+goff);
  1524.  
  1525.             lsprintf(title,"IFF ANIM : %s   %s %ld %s %ld   %ld x %ld x %s\n\n",
  1526.                 ptr,
  1527.                 globstring[STR_FRAME],
  1528.                 fnum,
  1529.                 globstring[STR_OF],
  1530.                 framecount+1,
  1531.                 bmhead.w,
  1532.                 bmhead.h,
  1533.                 cols);
  1534.         }
  1535.         else {
  1536.             lsprintf(buf,"%12s : %ld x %ld",
  1537.                 globstring[STR_PAGE_SIZE],
  1538.                 bmhead.pageWidth,
  1539.                 bmhead.pageHeight);
  1540.             iffinfotxt(prp,buf,7,43+goff);
  1541.  
  1542.             lsprintf(buf,"%12s : %ld x %ld",
  1543.                 globstring[STR_SCREEN_SIZE],
  1544.                 iffscreen->Width,
  1545.                 iffscreen->Height);
  1546.             iffinfotxt(prp,buf,7,51+goff);
  1547.  
  1548.             lsprintf(title,"IFF ILBM : %s   %ld x %ld x %s\n\n",
  1549.                 ptr,
  1550.                 bmhead.w,
  1551.                 bmhead.h,
  1552.                 cols);
  1553.         }
  1554.         lsprintf(buf,"%12s : %ld",
  1555.             globstring[STR_DEPTH],
  1556.             bmhead.nPlanes);
  1557.         iffinfotxt(prp,buf,7,67+goff);
  1558.  
  1559.         lsprintf(buf,"%12s : %s",
  1560.             globstring[STR_COLOURS],
  1561.             cols);
  1562.         iffinfotxt(prp,buf,7,75+goff);
  1563.  
  1564.         getviewmodes(modes);
  1565.         lsprintf(buf,"%12s : %s",
  1566.             globstring[STR_SCREEN_MODES],
  1567.             modes);
  1568.         iffinfotxt(prp,buf,7,83+goff);
  1569.     }
  1570.     else if (show_global_font) {
  1571.         char fontname[40],*ptr;
  1572.  
  1573.         strcpy(fontname,show_global_font->tf_Message.mn_Node.ln_Name);
  1574.         if (ptr=strstri(fontname,".font")) *ptr=0;
  1575.  
  1576.         lsprintf(buf,"%12s : %s",
  1577.             globstring[STR_FONT],
  1578.             fontname);
  1579.         iffinfotxt(prp,buf,7,19+goff);
  1580.  
  1581.         lsprintf(buf,"%12s : %ld",
  1582.             globstring[STR_FONT_SIZE],
  1583.             show_global_font->tf_YSize);
  1584.         iffinfotxt(prp,buf,7,35+goff);
  1585.  
  1586.         lsprintf(buf,"%12s : %ld (%ld - %ld)",
  1587.             globstring[STR_NUM_CHARS],
  1588.             (show_global_font->tf_HiChar-show_global_font->tf_LoChar)+1,
  1589.             show_global_font->tf_LoChar,
  1590.             show_global_font->tf_HiChar);
  1591.         iffinfotxt(prp,buf,7,51+goff);
  1592.  
  1593.         lsprintf(buf,"%12s :",
  1594.             globstring[STR_FONT_STYLE]);
  1595.         if ((show_global_font->tf_Style&15)==0) strcat(buf," NORMAL");
  1596.         else {
  1597.             if (show_global_font->tf_Style&FSF_UNDERLINED) strcat(buf," ULINED");
  1598.             if (show_global_font->tf_Style&FSF_BOLD) strcat(buf," BOLD");
  1599.             if (show_global_font->tf_Style&FSF_ITALIC) strcat(buf," ITALIC");
  1600.             if (show_global_font->tf_Style&FSF_EXTENDED) strcat(buf," EXTEND");
  1601.         }
  1602.         iffinfotxt(prp,buf,7,67+goff);
  1603.  
  1604.         lsprintf(buf,"%12s :",globstring[STR_FONT_FLAGS]);
  1605.         if (show_global_font->tf_Flags&FPF_TALLDOT) strcat(buf," TALL");
  1606.         if (show_global_font->tf_Flags&FPF_WIDEDOT) strcat(buf," WIDE");
  1607.         if (show_global_font->tf_Flags&FPF_PROPORTIONAL)
  1608.             strcat(buf," PROP");
  1609.         iffinfotxt(prp,buf,7,75+goff);
  1610.  
  1611.         lsprintf(title,"Font : %s/%ld   %ld chars (%ld - %ld)\n\n",
  1612.             fontname,show_global_font->tf_YSize,
  1613.             (show_global_font->tf_HiChar-show_global_font->tf_LoChar)+1,
  1614.             show_global_font->tf_LoChar,
  1615.             show_global_font->tf_HiChar);
  1616.     }
  1617.     else if (show_global_icon) {
  1618.         lsprintf(buf,"%12s : %s",
  1619.             globstring[STR_ICON],
  1620.             show_global_icon_name);
  1621.         iffinfotxt(prp,buf,7,27+goff);
  1622.  
  1623.         lsprintf(buf,"%12s : %s",
  1624.             globstring[STR_ICON_TYPE],
  1625.             icon_type_names[show_global_icon->do_Type-1]);
  1626.         iffinfotxt(prp,buf,7,43+goff);
  1627.  
  1628.         lsprintf(buf,"%12s : %s",
  1629.             globstring[STR_ICON_ALTERNATE],
  1630.             (show_global_icon->do_Gadget.Flags&GFLG_GADGHIMAGE)?
  1631.             globstring[STR_YES]:globstring[STR_NO]);
  1632.         iffinfotxt(prp,buf,7,59+goff);
  1633.  
  1634.         if (show_global_icon->do_DefaultTool) {
  1635.             lsprintf(buf,"%12s : %s",
  1636.                 globstring[STR_ICON_DEFAULTTOOL],
  1637.                 show_global_icon->do_DefaultTool);
  1638.             iffinfotxt(prp,buf,7,75+goff);
  1639.         }
  1640.         lsprintf(title,"Workbench %s : %s\n\n",
  1641.             globstring[STR_ICON],
  1642.             show_global_icon_name);
  1643.     }
  1644.  
  1645.     for (a=0;a<8;a++) printgadgets[a].TopEdge+=goff;
  1646.     printcheckimage.ImageData=(USHORT *)DOpusBase->pdb_check;
  1647.     AddGadgetBorders(&pkey,printgadgets,4,2,1);
  1648.     AddGadgetBorders(&pkey,&printgadgets[PRINT_OKAY],2,2,1);
  1649.     AddGadgets(pwin,printgadgets,printgadtxt,8,2,1,1);
  1650.  
  1651.     if (!firsttime) {
  1652.         struct Preferences prefs;
  1653.  
  1654.         GetPrefs(&prefs,sizeof(struct Preferences));
  1655.         print_gads_sel[PRINT_ASPECT]=prefs.PrintAspect;
  1656.         print_gads_sel[PRINT_IMAGE]=prefs.PrintImage;
  1657.         print_gads_sel[PRINT_SHADE]=prefs.PrintShade;
  1658.  
  1659.         firsttime=1;
  1660.     }
  1661.  
  1662.     for (a=0;a<4;a++) {
  1663.         DoCycleGadget(&printgadgets[a],
  1664.             pwin,
  1665.             print_gads_txt[a],
  1666.             print_gads_sel[a]);
  1667.     }
  1668.  
  1669.     ScreenToFront(pscr);
  1670.     ActivateWindow(pwin);
  1671.     save=main_proc->pr_WindowPtr;
  1672.     main_proc->pr_WindowPtr=(APTR)pwin;
  1673.  
  1674.     FOREVER {
  1675.         Wait(1<<pwin->UserPort->mp_SigBit);
  1676.         while (msg=(struct IntuiMessage *) GetMsg(pwin->UserPort)) {
  1677.             class=msg->Class; code=msg->Code; qual=msg->Qualifier;
  1678.             if (class==IDCMP_GADGETUP)
  1679.                 gadgetid=((struct Gadget *)msg->IAddress)->GadgetID;
  1680.             ReplyMsg((struct Message *) msg);
  1681.             switch (class) {
  1682.                 case IDCMP_VANILLAKEY:
  1683.                     if (qual&IEQUALIFIER_REPEAT) break;
  1684.                     for (a=0;a<6;a++) {
  1685.                         if (code==pactcode[a] || code==toupper(pactcode[a])) {
  1686.                             if (a<4) {
  1687.                                 if (code==toupper(pactcode[a])) qual|=IEQUALIFIER_LSHIFT;
  1688.                                 SelectGadget(pwin,&printgadgets[a]);
  1689.                                 gadgetid=a;
  1690.                                 goto docyclegads;
  1691.                             }
  1692.                             else if (a==4) {
  1693.                                 printgadgets[4].Flags^=GFLG_SELECTED;
  1694.                                 RefreshGList(&printgadgets[4],pwin,NULL,1);
  1695.                             }
  1696.                             else if (a==5) {
  1697.                                 printgadgets[5].Flags^=GFLG_SELECTED;
  1698.                                 RefreshGList(&printgadgets[5],pwin,NULL,1);
  1699.                             }
  1700.                         }
  1701.                     }
  1702.                     if (code==globstring[STR_PRINT][0]) {
  1703.                         SelectGadget(pwin,&printgadgets[6]);
  1704.                         goto doprint;
  1705.                     }
  1706.                     else if (code=='' || code==' ' || code==tolower(str_cancelstring[0])) {
  1707.                         SelectGadget(pwin,&printgadgets[7]);
  1708.                         goto endprint;
  1709.                     }
  1710.                     break;
  1711.  
  1712.                 case IDCMP_GADGETUP:
  1713.                     if (gadgetid<PRINT_FORMFD) {
  1714. docyclegads:
  1715.                         if (qual&IEQUALIFIER_ANYSHIFT) {
  1716.                             if ((--print_gads_sel[gadgetid])<0)
  1717.                                 print_gads_sel[gadgetid]=print_gads_max[gadgetid];
  1718.                         }
  1719.                         else {
  1720.                             if ((++print_gads_sel[gadgetid])>print_gads_max[gadgetid])
  1721.                                 print_gads_sel[gadgetid]=0;
  1722.                         }
  1723.                         DoCycleGadget(&printgadgets[gadgetid],
  1724.                             pwin,
  1725.                             print_gads_txt[gadgetid],
  1726.                             print_gads_sel[gadgetid]);
  1727.                     }
  1728.                     else switch (gadgetid) {
  1729.                         case PRINT_CANCEL:
  1730.                             goto endprint;
  1731.                         case PRINT_OKAY:
  1732.                             goto doprint;
  1733.                     }
  1734.                     break;
  1735.             }
  1736.         }
  1737.     }
  1738. doprint:
  1739.     RemoveGList(pwin,printgadgets,-1);
  1740.     SetAPen(prp,0);
  1741.     RectFill(prp,0,0,319,pwin->Height-1);
  1742.     SetAPen(prp,1);
  1743.     abortprintgad.TopEdge=(pwin->Height-80)/2;
  1744.     AddGadgetBorders(&pkey,&abortprintgad,1,2,1);
  1745.     AddGadgets(pwin,&abortprintgad,printabortgadtxt,1,2,1,1);
  1746.     SetBusyPointer(pwin);
  1747.     if (print_request=(union printerIO *) LCreateExtIO(general_port,sizeof(union printerIO))) {
  1748.         if (!(OpenDevice("printer.device",0,(struct IORequest *)print_request,0))) {
  1749.             pd=(struct PrinterData *)print_request->iodrp.io_Device;
  1750.             prefs=&pd->pd_Preferences;
  1751.             prefs->PrintAspect=print_gads_sel[PRINT_ASPECT];
  1752.             prefs->PrintImage=print_gads_sel[PRINT_IMAGE];
  1753.             prefs->PrintShade=print_gads_sel[PRINT_SHADE];
  1754.             prefs->PrintXOffset=0;
  1755.  
  1756.             print_request->ios.io_Command=CMD_WRITE;
  1757.             print_request->ios.io_Data="\033#1";
  1758.             print_request->ios.io_Length=-1;
  1759.             while (DoIO((struct IORequest *)print_request)) {
  1760.                 reqoverride=pwin;
  1761.                 a=simplerequest(globstring[STR_ERROR_INITIALISING_PRINTER],
  1762.                     globstring[STR_TRY_AGAIN],str_cancelstring,NULL);
  1763.                 reqoverride=NULL;
  1764.                 if (!a) goto closeprinter;
  1765.             }
  1766.  
  1767.             if (printgadgets[5].Flags&GFLG_SELECTED) {
  1768.                 print_request->ios.io_Command=CMD_WRITE;
  1769.                 print_request->ios.io_Data=title;
  1770.                 print_request->ios.io_Length=-1;
  1771.                 if (DoIO((struct IORequest *)print_request)) goto closeprinter;
  1772.             }
  1773.  
  1774.             print_request->iodrp.io_Command=PRD_DUMPRPORT;
  1775.             print_request->iodrp.io_RastPort=rast;
  1776.             print_request->iodrp.io_ColorMap=wind->WScreen->ViewPort.ColorMap;
  1777.             if (system_version2) {
  1778.                 print_request->iodrp.io_Modes=GetVPModeID(&(wind->WScreen->ViewPort));
  1779.             }
  1780.             else {
  1781.                 print_request->iodrp.io_Modes=wind->WScreen->ViewPort.Modes;
  1782.             }
  1783.             print_request->iodrp.io_SrcX=x;
  1784.             print_request->iodrp.io_SrcY=y;
  1785.             print_request->iodrp.io_SrcWidth=w;
  1786.             print_request->iodrp.io_SrcHeight=h;
  1787.             print_request->iodrp.io_Special=SPECIAL_FULLCOLS|SPECIAL_ASPECT|SPECIAL_NOFORMFEED;
  1788.             if (!print_gads_sel[PRINT_PLACE])
  1789.                 print_request->iodrp.io_Special|=SPECIAL_CENTER;
  1790.             if (!(printgadgets[4].Flags&GFLG_SELECTED))
  1791.                 print_request->iodrp.io_Special|=SPECIAL_NOFORMFEED;
  1792.  
  1793.             SendIO((struct IORequest *)print_request);
  1794.             FOREVER {
  1795.                 Wait(1<<pwin->UserPort->mp_SigBit|1<<general_port->mp_SigBit);
  1796.                 while (GetMsg(general_port));
  1797.                 while (msg=(struct IntuiMessage *) GetMsg(pwin->UserPort)) {
  1798.                     class=msg->Class;
  1799.                     if (class==IDCMP_GADGETUP)
  1800.                         gadgetid=((struct Gadget *)msg->IAddress)->GadgetID;
  1801.                     ReplyMsg((struct Message *) msg);
  1802.                     if (class==IDCMP_GADGETUP && gadgetid==PRINT_ABORT) {
  1803.                         reqoverride=pwin;
  1804.                         abort=simplerequest(globstring[STR_REALLY_ABORT_PRINT],
  1805.                             globstring[STR_ABORT],globstring[STR_CONTINUE],NULL);
  1806.                         reqoverride=NULL;
  1807.                         if (abort) AbortIO((struct IORequest *)print_request);
  1808.                         break;
  1809.                     }
  1810.                 }
  1811.                 if (abort || (CheckIO((struct IORequest *)print_request))) break;
  1812.             }
  1813.             WaitIO((struct IORequest *)print_request);
  1814.             if (!abort && printgadgets[4].Flags&GFLG_SELECTED) {
  1815.                 print_request->ios.io_Command=CMD_WRITE;
  1816.                 print_request->ios.io_Data="\f";
  1817.                 print_request->ios.io_Length=-1;
  1818.                 DoIO((struct IORequest *)print_request);
  1819.             }
  1820. closeprinter:
  1821.             CloseDevice((struct IORequest *)print_request);
  1822.         }
  1823.         LDeleteExtIO((struct IORequest *)print_request);
  1824.     }
  1825. endprint:
  1826.     for (a=0;a<8;a++) printgadgets[a].TopEdge-=goff;
  1827.     main_proc->pr_WindowPtr=save;
  1828.     ActivateWindow(iffwindow);
  1829.     ScreenToBack(pscr);
  1830.     CloseWindow(pwin);
  1831.     CloseScreen(pscr);
  1832.     LFreeRemember(&pkey);
  1833. }
  1834.  
  1835. InitDHIRES(mp)
  1836. int mp;
  1837. {
  1838.     int line,creg,top,oscan,lace;
  1839.     struct UCopList *ucop;
  1840.  
  1841.     if (!(ucop=(struct UCopList *)AllocMem(sizeof(struct UCopList),MEMF_CLEAR)))
  1842.         return(0);
  1843.  
  1844.     lace=(viewflags&LACE)?1:0;
  1845.     top=copperheight;
  1846.     if (lace) top/=2;
  1847.  
  1848.     if (mp) {
  1849.         if (screenwidth>640) oscan=14;
  1850.         else oscan=16;
  1851.         CINIT(ucop,top*13);
  1852.         for (line=0;line<top;line++) {
  1853.             CWAIT(ucop,(line-1)<<lace,112);
  1854.             for (creg=4;creg<oscan;creg++) {
  1855.                 CMove(ucop,(long *)(0xdff180+(creg*2)),copperlist[(line<<(4+lace))+creg]);
  1856.                 CBump(ucop);
  1857.             }
  1858.         }
  1859.     }
  1860.     else {
  1861.         CINIT(ucop,copperheight*17);
  1862.         for (line=0;line<copperheight;line++) {
  1863.             CWAIT(ucop,line-1,122);
  1864.             for (creg=4;creg<16;creg++) {
  1865.                 CMove(ucop,(long *)(0xdff180+(creg*2)),copperlist[(line<<4)+creg]);
  1866.                 CBump(ucop);
  1867.             }
  1868.         }
  1869.     }
  1870.  
  1871.     CEND(ucop);
  1872.     Forbid();
  1873.     ivp->UCopIns=ucop;
  1874.     Permit();
  1875.     RethinkDisplay();
  1876.     return(1);
  1877. }
  1878.  
  1879. void getviewmodes(modes)
  1880. char *modes;
  1881. {
  1882.     if (iffscreenname[0]) strcpy(modes,iffscreenname);
  1883.     else {
  1884.         if (viewflags&SUPERHIRES) {
  1885.             strcpy(modes,"SUPERHIRES");
  1886.             if (bmhead.w>1280) strcat(modes," OSCAN");
  1887.         }
  1888.         else if (viewflags&HIRES) {
  1889.             strcpy(modes,"HIRES");
  1890.             if (bmhead.w>640) strcat(modes," OSCAN");
  1891.         }
  1892.         else {
  1893.             strcpy(modes,"LORES");
  1894.             if (bmhead.w>320) strcat(modes," OSCAN");
  1895.         }
  1896.         if (viewflags&LACE) strcat(modes," LACE");
  1897.     }
  1898.     if (copperlist) strcat(modes," DHIRES");
  1899.     else if (pchghead) {
  1900.         if (sham) strcat(modes," SHAM");
  1901.         else strcat(modes," PCHG");
  1902.     }
  1903.     else {
  1904.         if (viewflags&HAM) strcat(modes," HAM");
  1905.         else if (viewflags&EXTRA_HALFBRITE) strcat(modes," EHB");
  1906.     }
  1907. }
  1908.  
  1909. void docheckrasscroll(scr)
  1910. struct Screen *scr;
  1911. {
  1912.     if (ivp->RasInfo->RxOffset+screenwidth>bitmapwidth)
  1913.         ivp->RasInfo->RxOffset=bitmapwidth-ivp->DWidth;
  1914.     if (ivp->RasInfo->RxOffset<0) ivp->RasInfo->RxOffset=0;
  1915.     if (ivp->RasInfo->RyOffset+screenheight>bitmapheight)
  1916.         ivp->RasInfo->RyOffset=bitmapheight-ivp->DHeight;
  1917.     if (ivp->RasInfo->RyOffset<0) ivp->RasInfo->RyOffset=0;
  1918.     MakeScreen(scr);
  1919.     RethinkDisplay();
  1920. }
  1921.  
  1922. void iffinfotxt(r,buf,x,y)
  1923. struct RastPort *r;
  1924. char *buf;
  1925. int x,y;
  1926. {
  1927.     int a,l;
  1928.  
  1929.     a=strlen(buf); l=(316-x)/8;
  1930.     Move(r,x,y);
  1931.     Text(r,buf,(a>l)?l:a);
  1932. }
  1933.  
  1934. void build_palettes(colourdata,coloursize,ctable4,ctable8)
  1935. unsigned char *colourdata;
  1936. int coloursize;
  1937. UWORD *ctable4;
  1938. ULONG *ctable8;
  1939. {
  1940.     int a,b;
  1941.     unsigned int rgb[3];
  1942.  
  1943.     if (ctable8) {
  1944.         for (a=0,b=1;a<coloursize;a++,b++)
  1945. /*
  1946.             ctable8[b]=(colourdata[a]<<24)|0x00ffffff;
  1947. */
  1948.             ctable8[b]=
  1949.                 ((colourdata[a]<<24)&0xff000000)|
  1950.                 ((colourdata[a]<<16)&0x00ff0000)|
  1951.                 ((colourdata[a]<<8)&0x0000ff00)|
  1952.                 ((colourdata[a]&0x000000ff));
  1953.  
  1954.         ctable8[0]=numcolours<<16;
  1955.         ctable8[(numcolours*3)+1]=0;
  1956.     }
  1957.  
  1958.     if (ctable4) {
  1959.         for (a=0;a<numcolours;a++) {
  1960.             for (b=0;b<3;b++) rgb[b]=(unsigned int)(((unsigned char)(*(colourdata++)))>>4);
  1961.             ctable4[a]=(rgb[0]<<8)+(rgb[1]<<4)+rgb[2];
  1962.         }
  1963.     }
  1964. }
  1965.